package entity

import (
	"fmt"
	"server/world/scene"
)

var _ scene.Entity = (*Player)(nil)

// Player 玩家结构，实现Entity接口
type Player struct {
	Entity
	uid string
	//mu     sync.RWMutex
	Speed  float64 //移动速度
	Radius float64 //视野范围
}

// NewPlayer 创建新玩家
func NewPlayer(id int32, x, y float64) (*Player, error) {
	p := &Player{}
	p.x, p.y = x, y
	p.status = int32(scene.EntityStatusChangeScene)
	sc := scene.Get(id)
	if sc == nil {
		return nil, fmt.Errorf("scene not exist")
	}
	if !sc.Join(p, x, y) {
		return nil, fmt.Errorf("scene join failed")
	}
	return p, nil
}

func (p *Player) GetUid() string {
	return p.uid
}

// GetType 获取实体类型，实现Entity接口
func (p *Player) GetType() scene.EntityType {
	return scene.EntityTypePlayer
}

// ChangeScene 场景传送
func (p *Player) ChangeScene(id int32, x, y float64) bool {
	sc := scene.Get(id)
	if sc == nil {
		return false
	}
	if !p.SetStatus(scene.EntityStatusNone, scene.EntityStatusChangeScene) {
		return false
	}
	defer func() {
		p.status = int32(scene.EntityStatusNone)
	}()

	return p.leaveScene(func() bool {
		return p.joinScene(id, x, y)
	})
}

func (p *Player) joinScene(id int32, x, y float64) bool {
	sc := scene.Get(id)
	if sc == nil {
		return false
	}
	return sc.Join(p, x, y)
}
func (p *Player) leaveSceneNext() bool {
	return true
}
func (p *Player) leaveScene(next ...func() bool) bool {
	var done func() bool
	if len(next) == 0 {
		done = p.leaveSceneNext
	} else {
		done = next[0]
	}
	x, y := p.x, p.y
	layer := p.layer
	if layer == nil {
		return done()
	}
	//修改状态为传送中，并广告给附近玩家
	near := p.GetNearPlayers()
	msg := NewPlayerStatus(p.id, scene.EntityStatusChangeScene)
	for _, v := range near {
		v.SendMessage(msg)
	}

	success := true
	if layer.Remove(p, x, y) {
		success = done()
	}

	if success {
		layer.Remove(p, x, y)
		lm := &SceneLevel{Message{T: MessageTypeLeave, K: p.id}}
		for _, v := range near {
			v.SendMessage(lm)
		}
	} else {
		//离开场景失败
		msg = NewPlayerStatus(p.id, scene.EntityStatusNone)
		for _, v := range near {
			v.SendMessage(msg)
		}
	}
	return success
}

// Remove 移除 实例
func (p *Player) Remove() {
	if p.layer == nil {
		return
	}
	near := p.GetNearPlayers()
	layer := p.layer
	layer.Remove(p, p.x, p.y)
	lm := &SceneLevel{Message{T: MessageTypeLeave, K: p.id}}
	for _, v := range near {
		v.SendMessage(lm)
	}
}

// UpdatePosition 更新玩家位置
func (p *Player) UpdatePosition(newX, newY float64) {
	if p.layer == nil {
		return
	}
	if !p.SetStatus(scene.EntityStatusNone, scene.EntityStatusMovement) {
		return
	}
	defer func() {
		p.status = int32(scene.EntityStatusNone)
	}()

	oldX, oldY := p.x, p.y
	layer := p.layer
	if layer.Move(p, newX, newY) {
		p.x, p.y = newX, newY
	}
	// 如果位置变化超过阈值，通知附近玩家
	if (oldX-newX)*(oldX-newX)+(oldY-newY)*(oldY-newY) > 1.0 {
		// 这里将在大世界系统中处理移动通知
		p.NotifyMovement()
	}
}
func (p *Player) GetNearPlayers() []*Player {
	var players []*Player
	if p.layer == nil {
		return players
	}
	ls := p.layer.GetNearEntities(p, p.Radius, scene.EntityTypePlayer)
	for _, l := range ls {
		players = append(players, l.(*Player))
	}
	return players
}

// NotifyMovement 通知附近玩家自己的移动
func (p *Player) NotifyMovement() {
	// 创建移动消息
	msg := Movement{
		Message: Message{
			T: MessageTypeMove,
			K: p.id,
		},
		Pos: &scene.Position{
			X: p.x,
			Y: p.y,
		},
	}
	// 广播给附近玩家
	for _, e := range p.GetNearPlayers() {
		e.SendMessage(msg)
	}
}

// SendMessage 发送消息给玩家（这里使用MOCK实现）
func (p *Player) SendMessage(msg interface{}) {
	// MOCK实现，实际项目中这里会调用网络模块发送消息
	//fmt.Printf("Player %d received message: %v\n", p.ID, msg)
}
